/*
 * This file is part of the Marmalade SDK Code Samples.
 *
 * (C) 2001-2012 Marmalade. All Rights Reserved.
 *
 * This source code is intended only as a supplement to the Marmalade SDK.
 *
 * THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 */

// Standard includes
#include "IwUILabel.h"
#include "IwUILayoutGrid.h"
#include "IwUITableView.h"
#include "IwUITableViewItemSource.h"
//#include "s3eContacts.h"

// Project includes
#include "IwUIDailyReport.h"
#include "DailyReportDataProvider.h"


static DailyReportDataProvider* gs_DailyReportDataProvider;

//-----------------------------------------------------------------------------

class CDailyReportsItemSource : public CIwUITableViewItemSource,
    public IDailyReportsItemSource
{
public:
    IW_MANAGED_DECLARE(CDailyReportsItemSource)
    CDailyReportsItemSource() :
        m_Active(false),
        m_ColumnWidth(-1),
        m_RowHeight(-1),
        m_Template(NULL),
        m_TemplateClone(NULL),
		m_DailyReportModel(new DailyReportModel())
    {
		m_DailyReportModel->RowId = -1;
    }

    virtual ~CDailyReportsItemSource()
    {
        IwAssert(UI, !m_TemplateClone);
		delete m_DailyReportModel;
        delete m_Template;
    }

private:
	// Convert string (format hh:mm:ss) to number (by second).
	int timetoint(char* pTime)
	{
		int result = 0;
		int time = 0;
		char* num = new char[3];
		// Get hour.
		num[0] = pTime[0];
		num[1] = pTime[1];
		num[3] = '\0';
		time = atoi(num);
		result += time * 3600;
		// Get minue.
		num[0] = pTime[3];
		num[1] = pTime[4];
		num[3] = '\0';
		time = atoi(num);
		result += time * 60;
		// Get minue.
		num[0] = pTime[6];
		num[1] = pTime[7];
		num[3] = '\0';
		time = atoi(num);
		result += time;

		delete[] num;
		return result;
	}

	char* inttotime(int pTime)
	{
		char* result = new char[10];
		char* num = new char[3];
		// Get hour.
		int time = pTime/3600;
		sprintf(num, "%d", time);
		result[0] = num[0];
		result[1] = num[1];
		pTime = pTime - (time * 3600);// get mod.
		// Get minue.
		time = pTime/60;
		sprintf(num, "%d", time);
		result[2] = ':';
		result[3] = num[0];
		result[4] = num[1];
		time = pTime - (time * 60);// get mod.
		// Get second.
		sprintf(num, "%d", time);
		result[5] = ':';
		result[6] = num[0];
		result[7] = num[1];

		result[8] = '\0';
		delete[] num;
		return result;
	}
    // IwManaged virtuals
    virtual void ParseCloseChild(CIwTextParserITX* pParser, CIwManaged* pChild)
    {
		// Child is "class CIwUITableViewItem"
        m_Template = IwSafeCast<CIwUIElement*>(pChild);
    }

    virtual void Serialise()
    {
        CIwUITableViewItemSource::Serialise();

        IwSerialiseManagedObject(*(CIwManaged**)&m_Template);
    }

    virtual void Resolve()
    {
        CIwUITableViewItemSource::Resolve();

        CIwManaged* pTemplate = m_Template;
        if (pTemplate)
        {
            pTemplate->Resolve();
        }
    }

    // IwUITableViewItemSource virtuals
    virtual bool IsRowAvailable(int32 row) const
    {
        return (0 <= row) && (row < (int32)m_DailyReportRowIds.size());
    }

    virtual CIwUIElement* CreateItem(int32 row)
    {
        IwAssert(UI, IsRowAvailable(row));

        const int32 rowId = m_DailyReportRowIds[row];

        // Store UID with item for future reference dailyReportUID
        CIwUIElement* pItem = m_Template->Clone();
        pItem->SetProperty("dailyReportUID", rowId);

		DailyReportModel* oDailyReportModel;
		if(rowId != m_DailyReportModel->RowId)
		{
			oDailyReportModel= new DailyReportModel();
			gs_DailyReportDataProvider->GetDataByRowId(oDailyReportModel, rowId);
		}
		else
			oDailyReportModel = m_DailyReportModel;

		//int time = timetoint(oDailyReportModel->StartTime);
		//char* ctime = inttotime(time);
		//delete[] ctime;

		CIwUILabel* col0;
		pItem->LookupChildNamed(col0,"TaskValue");
		col0->SetCaption(oDailyReportModel->TaskName);
		CIwUILabel* col1;
		pItem->LookupChildNamed(col1,"StartTimeVal");
		col1->SetCaption(oDailyReportModel->StartTime);
		CIwUILabel* col2;
		pItem->LookupChildNamed(col2,"EndTimeVal");
		col2->SetCaption(oDailyReportModel->EndTime);
		CIwUILabel* col3;
		pItem->LookupChildNamed(col3,"DurationVal");
		char* duration = new char[100];
		sprintf(duration, "%d", oDailyReportModel->Duration);
		col3->SetCaption(duration);
		delete duration;
		if(rowId != m_DailyReportModel->RowId)
			delete oDailyReportModel;
        return pItem;
    }

    virtual void ReleaseItem(CIwUIElement* pItem, int32 row)
    {
        delete pItem;
    }

    virtual int32 GetRowHeight(int32 row, int32 columnWidth) const
    {
        IwAssert(UI, IsRowAvailable(row));

        if (m_ColumnWidth != columnWidth)
        {
            CIwVec2 itemSize =
                m_TemplateClone->Measure(CIwVec2(columnWidth, LAYOUT_INFINITY));
            m_ColumnWidth = columnWidth;
            m_RowHeight = itemSize.y;
        }

        return m_RowHeight;
    }

    virtual void Activate(bool val)
    {
        CIwUITableViewItemSource::Activate(val);

        if (val)
        {
			// Init Data Provider.
			if(gs_DailyReportDataProvider == NULL)
				gs_DailyReportDataProvider = new DailyReportDataProvider();
            // Clone template item into table (making invisible)
            // so we can determine its size.
            m_TemplateClone = m_Template->Clone();
            m_TemplateClone->SetVisible(false);
            GetTableView()->AddChild(m_TemplateClone);

            // Attach to application
            GetApp()->SetActiveItemSource(this);

            // Cache UIDs
			UpdateAllItem();
        }
        else
        {
			// Delete Data Provider
 			if(gs_DailyReportDataProvider != NULL)
			{
				delete gs_DailyReportDataProvider;
				gs_DailyReportDataProvider = NULL;
			}
            GetApp()->SetActiveItemSource(NULL);
            m_DailyReportRowIds.clear();

            GetTableView()->RemoveChild(m_TemplateClone);
            delete m_TemplateClone;
            m_TemplateClone = NULL;
        }

        m_ColumnWidth = -1;
        m_RowHeight = -1;
        m_Active = val;
    }

    virtual void Clone(CIwUITableViewItemSource* pTarget) const
    {
        IW_UI_CLONE_SUPERCLASS(pTarget, CDailyReportsItemSource, CIwUITableViewItemSource);

        CDailyReportsItemSource* pItemSource = (CDailyReportsItemSource*) pTarget;
        pItemSource->m_Template = m_Template->Clone();
    }

    // DailyReportsItemSource virtuals
    virtual int32 GetRowIdByIndex(int32 pRowindex)
    {
        return (0 <= pRowindex) && (pRowindex < (int32)m_DailyReportRowIds.size()) ?
            m_DailyReportRowIds[pRowindex] : -1;
    }

    virtual int CreateItem(const char* pTaskName, const char* pBeginDate, const char* pStartTime, const char* pEndTime, int pDuration)
    {
		int rowId = -1;
        if (m_Active)
        {
			//DailyReportModel* oDailyReportModel = new DailyReportModel(rowId, pTaskName, pBeginDate, pStartTime, pEndTime, pDuration);
			m_DailyReportModel->RowId = rowId;
			strcpy(m_DailyReportModel->TaskName, pTaskName);
			strcpy(m_DailyReportModel->BeginDate, pBeginDate);
			strcpy(m_DailyReportModel->StartTime, pStartTime);
			strcpy(m_DailyReportModel->EndTime, pEndTime);
			strcpy(m_DailyReportModel->Description, "");
			m_DailyReportModel->Duration = pDuration;
		
			rowId = gs_DailyReportDataProvider->InsertData(m_DailyReportModel);
			m_DailyReportModel->RowId = rowId;
			//delete oDailyReportModel;
			// Add item at end
			int32 index = m_DailyReportRowIds.size();
			m_DailyReportRowIds.insert_slow(rowId, index);

            // Tell table of new row
            GetTableView()->InsertRow(index);

            // Show new dailyReport
            GetTableView()->SetSelection(index);
            GetTableView()->SetScrollToRow(index);
        }
		return rowId;
    }

	virtual void UpdateItemByRowId(int32 pRowId, const char* pTaskName, const char* pBeginDate, const char* pStartTime, const char* pEndTime, const char* pDes)
	{
	    // Find index for UID
        int32 index = m_DailyReportRowIds.find(pRowId);

        if (index != -1)
        {
            if (m_Active)
            {
				DailyReportModel* oDailyReportModel = new DailyReportModel();
				oDailyReportModel->RowId = pRowId;
				strcpy(oDailyReportModel->TaskName, pTaskName);
				strcpy(oDailyReportModel->BeginDate, pBeginDate);
				strcpy(oDailyReportModel->StartTime, pStartTime);
				strcpy(oDailyReportModel->EndTime, pEndTime);
				strcpy(oDailyReportModel->Description, pDes);
				gs_DailyReportDataProvider->UpdateDataWithoutDuration(oDailyReportModel);
				delete oDailyReportModel;
                // Tell table to update row
                GetTableView()->UpdateRow(index);
            }
        }
	}
    virtual void UpdateDoneByRowId(int32 pRowId, char* pEndDate, char* pEndTime)
    {
		pRowId = m_DailyReportModel->RowId;
		// Find index for UID
		int32 index = m_DailyReportRowIds.find(pRowId);
		if (index != -1)
		{
			if (m_Active)
			{
				if(m_DailyReportModel->RowId != -1)
				{
					// Update Duration into database.
					//DailyReportModel* oDailyReportModel = new DailyReportModel();
					// Get Data by rowid.
					//gs_DailyReportDataProvider->GetDataByRowId(oDailyReportModel, pRowId);
					char* endTime = new char[255];
					if(strcmp(pEndDate, m_DailyReportModel->BeginDate) != 0)
					{
						strcpy(endTime, "24:00:00");
					}
					else
					{
						strcpy(endTime, pEndTime);
					}
					// Update EndTime and Duration.
					strcpy(m_DailyReportModel->EndTime, endTime);
					// Process duration.
					int startTime = timetoint(m_DailyReportModel->StartTime);
					m_DailyReportModel->Duration = timetoint(endTime) - startTime;
					gs_DailyReportDataProvider->UpdateDataDone(m_DailyReportModel);
					//delete oDailyReportModel;
					delete endTime;

					m_DailyReportModel->RowId = -1;
					// Tell table to update row
					GetTableView()->UpdateRow(index);
				}
			}
		}
    }
	virtual void UpdateDurationByRowId(int pIncrement)
	{
        // Find index for UID
        int32 index = m_DailyReportRowIds.find(m_DailyReportModel->RowId);

        if (index != -1)
        {
            if (m_Active)
            {
				m_DailyReportModel->Duration += pIncrement;
                // Tell table to update row
                GetTableView()->UpdateRow(index);
            }
        }
	}

    virtual void DeleteItemByRowId(int32 pRowId)
    {
        // Find index for UID
        int32 index = m_DailyReportRowIds.find(pRowId);

        if (index != -1)
        {
            m_DailyReportRowIds.erase(index);

            if (m_Active)
            {
				gs_DailyReportDataProvider->DeleteData(pRowId);
                // Tell table to remove row
                GetTableView()->DeleteRow(index);
            }
        }
    }

	virtual void UpdateAllItem()
	{
		m_DailyReportRowIds.clear();
		gs_DailyReportDataProvider->GetsAllRowId(&m_DailyReportRowIds);
	}

	virtual void GetDataById(int pRowId, char* pTaskName, char* pBeginDate, char* pStartTime, char* pEndTime, char* pDes)
	{
		DailyReportModel* oDailyReportModel = new DailyReportModel();
		gs_DailyReportDataProvider->GetDataByRowId(oDailyReportModel, pRowId);
		strcpy(pTaskName, oDailyReportModel->TaskName);
		strcpy(pBeginDate, oDailyReportModel->BeginDate);
		strcpy(pStartTime, oDailyReportModel->StartTime);
		strcpy(pEndTime, oDailyReportModel->EndTime);
		if(oDailyReportModel->Description)
			strcpy(pDes, oDailyReportModel->Description);
		delete oDailyReportModel;
	}

	// Member data
	bool                m_Active;
	mutable int32       m_ColumnWidth;
	mutable int32       m_RowHeight;
	CIwUIElement*       m_Template;
	CIwUIElement*       m_TemplateClone;
	CIwArray<int32>     m_DailyReportRowIds;
	DailyReportModel*	m_DailyReportModel;
};

IW_MANAGED_IMPLEMENT_FACTORY(CDailyReportsItemSource);
